home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xpuzzles.3 / xpuzzles / xpuzzles-5.3.1 / xrubik / xrubik.c < prev    next >
C/C++ Source or Header  |  1996-02-05  |  13KB  |  448 lines

  1. /*
  2. # X-BASED RUBIK'S CUBE(tm)
  3. #
  4. #  xrubik.c
  5. #
  6. ###
  7. #
  8. #  Copyright (c) 1994 - 96    David Albert Bagley, bagleyd@hertz.njit.edu
  9. #
  10. #                   All Rights Reserved
  11. #
  12. #  Permission to use, copy, modify, and distribute this software and
  13. #  its documentation for any purpose and without fee is hereby granted,
  14. #  provided that the above copyright notice appear in all copies and
  15. #  that both that copyright notice and this permission notice appear in
  16. #  supporting documentation, and that the name of the author not be
  17. #  used in advertising or publicity pertaining to distribution of the
  18. #  software without specific, written prior permission.
  19. #
  20. #  This program is distributed in the hope that it will be "playable",
  21. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  23. #
  24. */
  25.  
  26. /*
  27.   Version 4: 94/04/07 Xt
  28.   Version 3: 93/05/20 Motif
  29.   Version 2: 92/01/16 XView
  30.   Version 1: 91/01/16 SunView
  31. */
  32.  
  33. #include <stdlib.h>
  34. #include <stdio.h>
  35. #ifdef VMS
  36. #include <unixlib.h>
  37. #define getlogin cuserid
  38. #else
  39. #ifndef apollo
  40. #include <unistd.h>        
  41. #endif
  42. #endif
  43. #include <X11/Intrinsic.h>
  44. #include <X11/StringDefs.h>
  45. #include <X11/Shell.h>
  46. #include <X11/cursorfont.h>
  47. #include "Rubik.h"
  48. #include "Rubik2d.h"
  49. #include "Rubik3d.h"
  50. #include "rubik.xbm"
  51.  
  52. #ifndef SCOREFILE
  53. #define SCOREFILE "/usr/games/lib/rubik.scores"
  54. #endif
  55.  
  56. /* The following are in RubikP.h also */
  57. #define MINCUBES 1
  58. #define MAXFACES 6
  59.  
  60. #define MAXCUBES 6
  61. #define MAXRECORD 32767
  62. #define MAXPROGNAME 80
  63. #define MAXNAME 256
  64.  
  65. static void Initialize();
  66. static void CallbackRubik();
  67.  
  68. static void PrintRecord();
  69. static int HandleSolved();
  70. static void PrintState();
  71. static void ReadRecords();
  72. static void WriteRecords();
  73.  
  74. static Widget rubik2d, rubik3d;
  75. static Arg arg[4];
  76. static int rubikRecord[2][MAXCUBES - MINCUBES + 1], movesDsp = 0;
  77. static char progDsp[64] = "xrubik";
  78. static char recordDsp[16] = "INF";
  79. static char messageDsp[128] = "Welcome";
  80. static char titleDsp[256] = "";
  81.  
  82. static void Usage()
  83. {
  84.   (void) fprintf(stderr, "usage: xrubik\n");
  85.   (void) fprintf(stderr,
  86.     "\t[-geometry [{width}][x{height}][{+-}{xoff}[{+-}{yoff}]]]\n");
  87.   (void) fprintf(stderr,
  88.     "\t[-display [{host}]:[{vs}]][-fg {color}] [-bg {color}]\n");
  89.   (void) fprintf(stderr,
  90.     "\t[-{border|bd} {color}] [-mono] [-size {int}] [-[no]orient]\n");
  91.   (void) fprintf(stderr,
  92.     "\t[-[no]practice] [-face{0|1|2|3|4|5} {color}]\n");
  93.   exit(1);
  94. }
  95.  
  96. static XrmOptionDescRec options[] = {
  97.   {"-fg",        "*rubik.Foreground",    XrmoptionSepArg,    NULL},
  98.   {"-bg",        "*Background",        XrmoptionSepArg,    NULL},
  99.   {"-foreground",    "*rubik.Foreground",    XrmoptionSepArg,    NULL},
  100.   {"-background",    "*Background",        XrmoptionSepArg,    NULL},
  101.   {"-border",        "*rubik.pieceBorder",    XrmoptionSepArg,    NULL},
  102.   {"-bd",        "*rubik.pieceBorder",    XrmoptionSepArg,    NULL},
  103.   {"-mono",        "*rubik.mono",        XrmoptionNoArg,        "TRUE"},
  104.   {"-size",        "*rubik.size",        XrmoptionSepArg,    NULL},
  105.   {"-orient",        "*rubik.orient",    XrmoptionNoArg,        "TRUE"},
  106.   {"-noorient",        "*rubik.orient",    XrmoptionNoArg,        "FALSE"},
  107.   {"-practice",        "*rubik.practice",    XrmoptionNoArg,        "TRUE"},
  108.   {"-nopractice",    "*rubik.practice",    XrmoptionNoArg,        "FALSE"},
  109.   {"-face0",        "*rubik.faceColor0",    XrmoptionSepArg,    NULL},
  110.   {"-face1",        "*rubik.faceColor1",    XrmoptionSepArg,    NULL},
  111.   {"-face2",        "*rubik.faceColor2",    XrmoptionSepArg,    NULL},
  112.   {"-face3",        "*rubik.faceColor3",    XrmoptionSepArg,    NULL},
  113.   {"-face4",        "*rubik.faceColor4",    XrmoptionSepArg,    NULL},
  114.   {"-face5",        "*rubik.faceColor5",    XrmoptionSepArg,    NULL},
  115. };
  116.  
  117. int main(argc, argv)
  118.   int argc;
  119.   char *argv[];
  120. {
  121.   Widget toplevel, shell;
  122.  
  123.   toplevel = XtInitialize(argv[0], "Rubik",
  124.     options, XtNumber(options), &argc, argv);
  125.   if (argc != 1)
  126.     Usage();
  127.  
  128.   shell = XtCreateApplicationShell(argv[0], topLevelShellWidgetClass, NULL,
  129.     0);
  130.   XtSetArg(arg[0], XtNiconPixmap,
  131.     XCreateBitmapFromData(XtDisplay(toplevel),
  132.       RootWindowOfScreen(XtScreen(toplevel)),
  133.       (char *) rubik_bits, rubik_width, rubik_height));
  134.   XtSetValues(toplevel, arg, 1);
  135.   XtSetArg(arg[0], XtNiconPixmap, 
  136.     XCreateBitmapFromData(XtDisplay(shell),
  137.       RootWindowOfScreen(XtScreen(shell)),
  138.       (char *) rubik_bits, rubik_width, rubik_height));
  139.   XtSetValues(shell, arg, 1);
  140.   rubik2d = XtCreateManagedWidget("rubik", rubik2dWidgetClass, toplevel,
  141.     NULL, 0);
  142.   XtAddCallback(rubik2d, XtNselectCallback, CallbackRubik, NULL);
  143.   rubik3d = XtCreateManagedWidget("rubik", rubik3dWidgetClass, shell,
  144.     NULL, 0);
  145.   XtAddCallback(rubik3d, XtNselectCallback, CallbackRubik, NULL);
  146.   Initialize();
  147.   XtRealizeWidget(toplevel);
  148.   XtRealizeWidget(shell);
  149.   XGrabButton(XtDisplay(rubik2d), AnyButton, AnyModifier, XtWindow(rubik2d),
  150.     TRUE, ButtonPressMask | ButtonMotionMask | ButtonReleaseMask,
  151.     GrabModeAsync, GrabModeAsync, XtWindow(rubik2d),
  152.     XCreateFontCursor(XtDisplay(rubik2d), XC_crosshair));
  153.   XGrabButton(XtDisplay(rubik3d), AnyButton, AnyModifier, XtWindow(rubik3d),
  154.     TRUE, ButtonPressMask | ButtonMotionMask | ButtonReleaseMask,
  155.     GrabModeAsync, GrabModeAsync, XtWindow(rubik3d),
  156.     XCreateFontCursor(XtDisplay(rubik3d), XC_crosshair));
  157.   XtMainLoop();
  158.  
  159. #ifdef VMS
  160.   return 1;
  161. #else
  162.   return 0;
  163. #endif
  164. }
  165.  
  166. /* There's probably a better way to assure that they are the same but
  167.    I don't know it off hand. */
  168. static void MakeEquivalent(size, orient, practice)
  169.   int *size;
  170.   Boolean *orient, *practice;
  171. {
  172.   Boolean mono;
  173.   Pixel foreground, background, pieceBorder;
  174.   String faceColor[MAXFACES];
  175.  
  176.   XtVaGetValues(rubik2d,
  177.     XtNsize, size,
  178.     XtNorient, orient,
  179.     XtNpractice, practice,
  180.     XtNmono, &mono,
  181.     XtNforeground, &foreground,
  182.     XtNbackground, &background,
  183.     XtNpieceBorder, &pieceBorder,
  184.     XtNfaceColor0, &(faceColor[0]),
  185.     XtNfaceColor1, &(faceColor[1]),
  186.     XtNfaceColor2, &(faceColor[2]),
  187.     XtNfaceColor3, &(faceColor[3]),
  188.     XtNfaceColor4, &(faceColor[4]),
  189.     XtNfaceColor5, &(faceColor[5]),
  190.     NULL);
  191.   XtVaSetValues(rubik2d,
  192.     XtNdirection, RUBIK_IGNORE,
  193.     XtNstart, FALSE,
  194.     NULL);
  195.   XtVaSetValues(rubik3d,
  196.     XtNsize, *size,
  197.     XtNorient, *orient,
  198.     XtNmono, mono,
  199.     XtNdirection, RUBIK_IGNORE,
  200.     XtNpractice, *practice,
  201.     XtNstart, FALSE,
  202.     XtNforeground, foreground,
  203.     XtNbackground, background,
  204.     XtNpieceBorder, pieceBorder,
  205.     XtNfaceColor0, faceColor[0],
  206.     XtNfaceColor1, faceColor[1],
  207.     XtNfaceColor2, faceColor[2],
  208.     XtNfaceColor3, faceColor[3],
  209.     XtNfaceColor4, faceColor[4],
  210.     XtNfaceColor5, faceColor[5],
  211.     NULL);
  212. }
  213.  
  214. static void Initialize()
  215. {
  216.   int size;
  217.   Boolean orient, practice;
  218.  
  219.   MakeEquivalent(&size, &orient, &practice);
  220.   ReadRecords();
  221.   PrintRecord(size, orient, practice, recordDsp);
  222.   PrintState(XtParent(rubik2d), progDsp, 2, size, movesDsp,
  223.     recordDsp, messageDsp);
  224.   PrintState(XtParent(rubik3d), progDsp, 3, size, movesDsp,
  225.     recordDsp, messageDsp);
  226. }
  227.  
  228. static void CallbackRubik(w, clientData, callData)
  229.   Widget w;
  230.   caddr_t clientData;
  231.   rubikCallbackStruct *callData;
  232. {
  233.   int size, dim, otherdim;
  234.   Boolean orient, practice, start;
  235.   Widget otherw;
  236.  
  237.   if (w == rubik2d) {
  238.     dim = 2;
  239.     otherw = rubik3d;
  240.     otherdim = 3;
  241.   } else { /* (w == rubik3d) */
  242.     dim = 3;
  243.     otherw = rubik2d;
  244.     otherdim = 2;
  245.   }
  246.   XtVaGetValues(w,
  247.     XtNsize, &size,
  248.     XtNorient, &orient,
  249.     XtNpractice, &practice,
  250.     XtNstart, &start,
  251.     NULL);
  252.   (void) strcpy(messageDsp, "");
  253.   switch (callData->reason) {
  254.     case RUBIK_RESTORE:
  255.       XtSetArg(arg[0], XtNdirection, RUBIK_RESTORE);
  256.       XtSetValues(otherw, arg, 1);
  257.       XtSetValues(w, arg, 1);
  258.       movesDsp = 0;
  259.       break;
  260.     case RUBIK_RESET:
  261.       movesDsp = 0;
  262.       break;
  263.     case RUBIK_ILLEGAL:
  264.       if (practice || start)
  265.         (void) strcpy(messageDsp, "Illegal move");
  266.       else
  267.         (void) strcpy(messageDsp, "Randomize to start");
  268.       break;
  269.     case RUBIK_MOVED:
  270.       movesDsp++;
  271. #ifdef DEBUG
  272.       if (movesDsp > 256)
  273.     exit(1);
  274. #endif
  275.       XtSetArg(arg[0], XtNstart, TRUE);
  276.       XtSetArg(arg[1], XtNface, callData->face);
  277.       XtSetArg(arg[2], XtNpos, callData->position);
  278.       XtSetArg(arg[3], XtNdirection, callData->direction);
  279.       XtSetValues(otherw, arg, 4);
  280.       XtSetValues(w, arg, 1);
  281.       break;
  282.     case RUBIK_CONTROL:
  283.       XtSetArg(arg[0], XtNface, callData->face);
  284.       XtSetArg(arg[1], XtNpos, callData->position);
  285.       XtSetArg(arg[2], XtNdirection, callData->direction);
  286.       XtSetValues(otherw, arg, 3);
  287.       return;
  288.     case RUBIK_SOLVED:
  289.       if (practice)
  290.         movesDsp = 0;
  291.       else { 
  292.         if (HandleSolved(movesDsp, size, orient))
  293.           (void) sprintf(messageDsp, "Congratulations %s!!", getlogin());
  294.         else
  295.           (void) strcpy(messageDsp, "Solved!");
  296.       }
  297.       XtSetArg(arg[0], XtNstart, FALSE);
  298.       XtSetValues(w, arg, 1);
  299.       XtSetValues(otherw, arg, 1);
  300.       break;
  301.     case RUBIK_PRACTICE:
  302.       movesDsp = 0;
  303.       practice = !practice;
  304.       if (!practice)
  305.         (void) strcpy(messageDsp, "Randomize to start");
  306.       PrintRecord(size, orient, practice, recordDsp);
  307.       XtSetArg(arg[0], XtNpractice, practice);
  308.       XtSetArg(arg[1], XtNstart, FALSE);
  309.       XtSetValues(w, arg, 2);
  310.       XtSetValues(otherw, arg, 2);
  311.       break;
  312.     case RUBIK_RANDOMIZE:
  313.       movesDsp = 0;
  314.       XtSetArg(arg[0], XtNpractice, FALSE);
  315.       XtSetArg(arg[1], XtNstart, FALSE);
  316.       XtSetValues(w, arg, 2);
  317.       XtSetValues(otherw, arg, 2);
  318.       break; 
  319.     case RUBIK_DEC:
  320.       movesDsp = 0;
  321.       size--;
  322.       PrintRecord(size, orient, practice, recordDsp);
  323.       XtSetArg(arg[0], XtNsize, size);
  324.       XtSetValues(w, arg, 1);
  325.       XtSetValues(otherw, arg, 1);
  326.       break;
  327.     case RUBIK_ORIENT:
  328.       movesDsp = 0;
  329.       orient = !orient;
  330.       PrintRecord(size, orient, practice, recordDsp);
  331.       XtSetArg(arg[0], XtNorient, orient);
  332.       XtSetValues(w, arg, 1);
  333.       XtSetValues(otherw, arg, 1);
  334.       break;
  335.     case RUBIK_INC:
  336.       movesDsp = 0;
  337.       size++;
  338.       PrintRecord(size, orient, practice, recordDsp);
  339.       XtSetArg(arg[0], XtNsize, size);
  340.       XtSetValues(w, arg, 1);
  341.       XtSetValues(otherw, arg, 1);
  342.       break;
  343.     case RUBIK_COMPUTED:
  344.       XtSetArg(arg[0], XtNstart, FALSE);
  345.       XtSetValues(w, arg, 1);
  346.       XtSetValues(otherw, arg, 1);
  347.       break;
  348.     case RUBIK_UNDO:
  349.       movesDsp--;
  350.       XtSetArg(arg[0], XtNstart, TRUE);
  351.       XtSetArg(arg[1], XtNface, callData->face);
  352.       XtSetArg(arg[2], XtNpos, callData->position);
  353.       XtSetArg(arg[3], XtNdirection, callData->direction);
  354.       XtSetValues(otherw, arg, 4);
  355.       XtSetValues(w, arg, 1);
  356.       break;
  357.   }
  358.   PrintState(XtParent(w), progDsp, dim, size, movesDsp,
  359.     recordDsp, messageDsp);
  360.   PrintState(XtParent(otherw), progDsp, otherdim, size, movesDsp,
  361.     recordDsp, messageDsp);
  362. }
  363.  
  364. static void PrintRecord(size, orient, practice, record)
  365.   int size;
  366.   Boolean orient, practice;
  367.   char *record;
  368. {
  369.   int i = (orient) ? 1 : 0;
  370.   int j = size - MINCUBES;
  371.  
  372.   if (practice)
  373.     (void) strcpy(record, "practice");
  374.   else if (size > MAXCUBES)
  375.     (void) strcpy(record, "NOT RECORDED");
  376.   else if (rubikRecord[i][j] >= MAXRECORD)
  377.     (void) strcpy(record, "NEVER");
  378.   else
  379.     (void) sprintf(record, "%d", rubikRecord[i][j]);
  380. }
  381.  
  382. static int HandleSolved(counter, size, orient)
  383.   int counter, size;
  384.   Boolean orient;
  385. {
  386.   int i = (orient) ? 1 : 0;
  387.   int j = size - MINCUBES;
  388.  
  389.   if (size <= MAXCUBES && counter < rubikRecord[i][j]) {
  390.     rubikRecord[i][j] = counter;
  391.     if (size < 2 || (orient && (rubikRecord[i][j] < rubikRecord[!i][j])))
  392.       rubikRecord[!i][j] = counter;
  393.     WriteRecords();
  394.     (void) sprintf(recordDsp, "%d", counter);
  395.     return TRUE;
  396.   }
  397.   return FALSE;
  398. }
  399.  
  400. static void PrintState(w, prog, dim, size, moves, record, message)
  401.   Widget w;
  402.   char *prog, *record, *message;
  403.   int dim, size, moves;
  404. {
  405.   (void) sprintf(titleDsp, "%s%dd: %d@ (%d/%s) - %s", prog, dim, size, moves,
  406.            record, message);
  407.   XtSetArg(arg[0], XtNtitle, titleDsp);
  408.   XtSetValues(w, arg, 1);
  409. }
  410.  
  411. static void ReadRecords()
  412. {
  413.   FILE *fp;
  414.   int i, n, orient;
  415.  
  416.   for (orient = 0; orient < 2; orient++)
  417.     for (i = 0; i < MAXCUBES - MINCUBES + 1; i++)
  418.       rubikRecord[orient][i] = MAXRECORD;
  419.   if ((fp = fopen(SCOREFILE, "r")) == NULL)
  420.     (void) sprintf(messageDsp,
  421.              "Can not open %s, taking defaults.", SCOREFILE);
  422.   else {
  423.     for (orient = 0; orient < 2; orient++)
  424.       for (i = 0; i < MAXCUBES - MINCUBES + 1; i++) {
  425.         (void) fscanf(fp, "%d", &n);
  426.         rubikRecord[orient][i] = n;
  427.       }
  428.     (void) fclose(fp);
  429.   }
  430. }
  431.  
  432. static void WriteRecords()
  433. {
  434.   FILE *fp;
  435.   int i, orient;
  436.  
  437.   if ((fp = fopen(SCOREFILE, "w")) == NULL)
  438.     (void) sprintf(messageDsp, "Can not write to %s.", SCOREFILE);
  439.   else {
  440.     for (orient = 0; orient < 2; orient++) {
  441.       for (i = 0; i < MAXCUBES - MINCUBES + 1; i++)
  442.         (void) fprintf(fp, "%d ", rubikRecord[orient][i]);
  443.       (void) fprintf(fp, "\n");
  444.     }
  445.     (void) fclose(fp);
  446.   }
  447. }
  448.